package session
//
//import (
//	"context"
//	"tsgo/types"
//	"tsgo/types/syntaxkind"
//)
//
//type SemanticMeaning = int
//
//const (
//	None SemanticMeaning = 0x0
//	Value SemanticMeaning = 0x1
//	Type SemanticMeaning = 0x2
//	Namespace SemanticMeaning = 0x4
//	All = Value | Type | Namespace
//)
//
//type ReferenceEntry struct {
//	TextSpan types.TextSpan
//	FileName string
//	IsWriteAccess bool
//	IsDefinition bool
//}
//
//type SymbolDisplayPart struct {
//	Text string
//	Kind string // A ScriptElementKind
//}
//
//type ReferencedSymbolDefinitionInfo struct {
//	DefinitionInfo
//	DisplayParts []SymbolDisplayPart
//}
//
//type ReferencedSymbol struct {
//	definition ReferencedSymbolDefinitionInfo
//	references []ReferenceEntry
//}
//
//func findReferencedSymbols(ctx context.Context, typeChecker types.ITypeChecker, sourceFiles []*types.SourceFile, sourceFile *types.SourceFile, position int, findInStrings bool, findInComments bool, isForRename bool) []ReferencedSymbol {
//	var ast = getTouchingPropertyName(sourceFile, position)
//	return getReferencedSymbolsForNode(ctx, typeChecker, ast, sourceFiles, findInStrings, findInComments, isForRename, false)
//}
//
//func convertReferences(referenceSymbols []ReferencedSymbol) []ReferenceEntry {
//	var result []ReferenceEntry
//	for _, r := range referenceSymbols {
//		result = append(result, r.references ...)
//	}
//	return result
//}
//
//func getReferencedSymbolsForNode(ctx context.Context,
//	typeChecker types.ITypeChecker,
//	ast *types.Node,
//	sourceFiles []*types.SourceFile,
//	findInStrings bool /*false*/,
//	findInComments bool /*false*/,
//	isForRename bool /*false*/,
//	implementations bool /*false*/) []ReferencedSymbol {
//	if !implementations {
//		var special = getReferencedSymbolsSpecial(ctx, ast, sourceFiles, typeChecker)
//		if special != nil {
//			return special
//		}
//	}
//
//	// `getSymbolAtLocation` normally returns the symbol of the class when given the constructor keyword,
//	// so we have to specify that we want the constructor symbol.
//	var symbol = typeChecker.GetSymbolAtLocation(ast)
//
//	// Could not find a symbol e.g. unknown identifier
//	if symbol == nil {
//		if !implementations && ast.Kind == syntaxkind.StringLiteral {
//			return getReferencesForStringLiteral(ctx, ast.ToLiteralExpression(), sourceFiles, typeChecker)
//		}
//		// Can't have references to something that we have no symbol for.
//		return nil
//	}
//
//	var declarations = symbol.Decls
//
//	// The symbol was an internal symbol and does not have a declaration e.g. undefined symbol
//	if len(declarations) == 0 {
//		return nil
//	}
//
//	aliasedSymbol, shorthandModuleSymbol := followAliases(symbol, ast, typeChecker, isForRename)
//	symbol = aliasedSymbol
//
//	// Build the set of symbols to search for, initially it has only the current symbol
//	var searchSymbols = populateSearchSymbolSet(symbol, ast, typeChecker, implementations)
//	if shorthandModuleSymbol != nil {
//		searchSymbols = append(searchSymbols, shorthandModuleSymbol)
//	}
//
//	// Compute the meaning from the location and the symbol it references
//	var searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(ast), declarations)
//
//	var result []ReferencedSymbol
//	// Maps from a symbol ID to the ReferencedSymbol entry in 'result'.
//	var symbolToIndex []int
//	inheritsFromCache := make(map[string]bool)
//
//	// Get the text to search for.
//	// Note if this is an external module symbol, the name doesn't include quotes.
//	var declaredName = stripQuotes(getDeclaredName(typeChecker, symbol, ast))
//
//	getRefs := func (scope *types.Node, searchName string) {
//		getReferencesInNode(ctx, scope, symbol, searchName, ast, searchMeaning, findInStrings, findInComments, result,
//			symbolToIndex, implementations, typeChecker, searchSymbols, inheritsFromCache)
//	}
//
//	// Try to get the smallest valid scope that we can limit our search to
//	// otherwise we'll need to search globally (i.e. include each file).
//	var scope = getSymbolScope(symbol)
//	if scope != nil {
//		getRefs(scope, declaredName)
//	} else {
//		var isDefault = isExportDefaultSymbol(symbol)
//		var internedName string
//		if isDefault {
//			internedName = symbol.ValueDecl
//		} else {
//			internedName = getInternedName(symbol, ast)
//		}
//
//		for _, sourceFile := range sourceFiles {
//
//			var searchName = (isDefault ? getDefaultImportName(symbol, sourceFile, typeChecker)  undefined) ||
//			(sourceFileHasName(sourceFile, internedName) ? declaredName  undefined)
//			if (searchName != undefined) {
//			getRefs(sourceFile, searchName)
//			}
//		}
//	}
//
//	return result
//}
//
///** getReferencedSymbols for special ast kinds. */
//func getReferencedSymbolsSpecial(ctx context.Context, ast *types.Node, sourceFiles []*types.SourceFile, typeChecker types.ITypeChecker) []ReferencedSymbol {
//	if (isTypeKeyword(ast.Kind)) {
//		return getAllReferencesForKeyword(sourceFiles, ast.Kind, cancellationToken)
//	}
//
//	// Labels
//	if (isLabelName(ast)) {
//		if (isJumpStatementTarget(ast)) {
//			var labelDefinition = getTargetLabel((<BreakOrContinueStatement>ast.Parent), (<Identifier>ast).text)
//			// if we have a label definition, look within its statement for references, if not, then
//			// the label is undefined and we have no results..
//			return labelDefinition && getLabelReferencesInNode(labelDefinition.Parent, labelDefinition, cancellationToken)
//		}
//		else {
//			// it is a label definition and not a target, search within the parent labeledStatement
//			return getLabelReferencesInNode(ast.Parent, <Identifier>ast, cancellationToken)
//		}
//	}
//
//	if (isThis(ast)) {
//		return getReferencesForThisKeyword(ast, sourceFiles, typeChecker, cancellationToken)
//	}
//
//	if (ast.Kind == syntaxkind.SuperKeyword) {
//		return getReferencesForSuperKeyword(ast, typeChecker, cancellationToken)
//	}
//
//	return undefined
//}
//
///**
// * Follows aliases to get to the original declaration of a symbol.
// * For a shorthand ambient module, we don't follow the alias to it, but we will need to add it to the set of search symbols.
// */
//func followAliases(symbol *types.Symbol, ast *types.Node, typeChecker types.ITypeChecker, isForRename bool) (*types.Symbol, *types.Symbol) /*{ symbol Symbol, shorthandModuleSymbol? Symbol }*/ {
//	while (true) {
//		// When renaming a default import, only rename in the current file
//		if (isForRename && isImportDefaultSymbol(symbol)) {
//			return { symbol }
//		}
//
//		var aliasedSymbol = getAliasSymbolForPropertyNameSymbol(symbol, ast, typeChecker)
//		// Don't follow alias if it goes to unknown symbol. This can happen if it points to an untyped module.
//		if (!aliasedSymbol || !aliasedSymbol.declarations) {
//			return { symbol }
//		}
//
//		if (ts.isShorthandAmbientModuleSymbol(aliasedSymbol)) {
//			return { symbol, shorthandModuleSymbol aliasedSymbol }
//		}
//
//		symbol = aliasedSymbol
//	}
//}
//
//func sourceFileHasName(sourceFile *types.SourceFile, name string) bool {
//	return getNameTable(sourceFile).get(name) != undefined
//}
//
///**
// * Given a symbol, see if any of the imports in a session file reference it.
// * Only call this if `symbol` is a default export.
// */
//func getDefaultImportName(symbol *types.Symbol, sourceFile *types.SourceFile, checker types.ITypeChecker) *string {
//	for (var importSpecifier of sourceFile.imports) {
//		var importDecl = importSpecifier.Parent as ts.ImportDeclaration
//		Debug.assert(importDecl.moduleSpecifier == importSpecifier)
//		var defaultName = importDecl.importClause.name
//		var defaultReferencedSymbol = defaultName && checker.getAliasedSymbol(checker.getSymbolAtLocation(defaultName))
//		if (symbol == defaultReferencedSymbol) {
//			return defaultName.text
//		}
//	}
//	return undefined
//}
//
//func getDefinition(symbol *types.Symbol, ast *types.Node, typeChecker types.ITypeChecker) ReferencedSymbolDefinitionInfo {
//	var { displayParts, symbolKind } = SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, ast.getSourceFile(), getContainerNode(ast), ast)
//	var name = displayParts.map(p => p.text).join("")
//	var declarations = symbol.declarations
//	if (!declarations || declarations.length == 0) {
//		return undefined
//	}
//
//	return {
//		containerKind "",
//		containerName "",
//		name,
//		kind symbolKind,
//		fileName declarations[0].getSourceFile().fileName,
//		textSpan createTextSpan(declarations[0].getStart(), 0),
//		displayParts
//	}
//}
//
//func getAliasSymbolForPropertyNameSymbol(symbol *types.Symbol, location *types.Node, typeChecker types.ITypeChecker) *types.Symbol {
//	if (!(symbol.flags & SymbolFlags.SEKAlias)) {
//		return undefined
//	}
//
//	// Default import get alias
//	var defaultImport = getDeclarationOfKind(symbol, syntaxkind.ImportClause)
//	if (defaultImport) {
//		return typeChecker.getAliasedSymbol(symbol)
//	}
//
//	var importOrExportSpecifier = <ImportOrExportSpecifier>forEach(symbol.declarations,
//		declaration => (declaration.Kind == syntaxkind.ImportSpecifier ||
//			declaration.Kind == syntaxkind.ExportSpecifier) ? declaration  undefined)
//	if (importOrExportSpecifier &&
//		// export { a }
//		(!importOrExportSpecifier.propertyName ||
//			// export {a as class } where a is location
//			importOrExportSpecifier.propertyName == location)) {
//		// If Import specifier -> get alias
//		// else Export specifier -> get local target
//		return importOrExportSpecifier.Kind == syntaxkind.ImportSpecifier ?
//			typeChecker.getAliasedSymbol(symbol)
//			typeChecker.getExportSpecifierLocalTargetSymbol(importOrExportSpecifier)
//	}
//}
//
//func followAliasIfNecessary(symbol *types.Symbol, location *types.Node, typeChecker types.ITypeChecker) *types.Symbol {
//	return getAliasSymbolForPropertyNameSymbol(symbol, location, typeChecker) || symbol
//}
//
//func getPropertySymbolOfDestructuringAssignment(location *types.Node, typeChecker types.ITypeChecker) {
//	return isArrayLiteralOrObjectLiteralDestructuringPattern(location.Parent.Parent) &&
//		typeChecker.getPropertySymbolOfDestructuringAssignment(<Identifier>location)
//}
//
//func isObjectBindingPatternElementWithoutPropertyName(symbol *types.Symbol) {
//	var bindingElement = <BindingElement>getDeclarationOfKind(symbol, syntaxkind.BindingElement)
//	return bindingElement &&
//		bindingElement.Parent.Kind == syntaxkind.ObjectBindingPattern &&
//		!bindingElement.propertyName
//}
//
//func getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol *types.Symbol, typeChecker types.ITypeChecker) {
//	if (isObjectBindingPatternElementWithoutPropertyName(symbol)) {
//		var bindingElement = <BindingElement>getDeclarationOfKind(symbol, syntaxkind.BindingElement)
//		var typeOfPattern = typeChecker.getTypeAtLocation(bindingElement.Parent)
//		return typeOfPattern && typeChecker.getPropertyOfType(typeOfPattern, (<Identifier>bindingElement.name).text)
//	}
//	return undefined
//}
//
//func getInternedName(symbol *types.Symbol, location *types.Node) string {
//	// If this is an export or import specifier it could have been renamed using the 'as' syntax.
//	// If so we want to search for whatever under the cursor.
//	if (isImportOrExportSpecifierName(location)) {
//		return location.text
//	}
//
//	return stripQuotes(symbol.name)
//}
//
///**
// * Determines the smallest scope in which a symbol may have named references.
// * Note that not every construct has been accounted for. This function can
// * probably be improved.
// *
// * @returns undefined if the scope cannot be determined, implying that
// * a reference to a symbol can occur anywhere.
// */
//func getSymbolScope(symbol *types.Symbol) *types.Node {
//	// If this is the symbol of a named function expression or named class expression,
//	// then named references are limited to its own scope.
//	var valueDeclaration = symbol.valueDeclaration
//	if (valueDeclaration && (valueDeclaration.Kind == syntaxkind.ArrowFunction || valueDeclaration.Kind == syntaxkind.ClassExpression)) {
//		return valueDeclaration
//	}
//
//	// If this is private property or method, the scope is the containing class
//	if (symbol.flags & (SymbolFlags.Property | SymbolFlags.Method)) {
//		var privateDeclaration = forEach(symbol.getDeclarations(), d => (getModifierFlags(d) & ModifierFlags.Private) ? d  undefined)
//		if (privateDeclaration) {
//			return getAncestor(privateDeclaration, syntaxkind.ClassDeclaration)
//		}
//	}
//
//	// If the symbol is an import we would like to find it if we are looking for what it imports.
//	// So consider it visible outside its declaration scope.
//	if (symbol.flags & SymbolFlags.SEKAlias) {
//		return undefined
//	}
//
//	// If symbol is of object binding pattern element without property name we would want to
//	// look for property too and that could be anywhere
//	if (isObjectBindingPatternElementWithoutPropertyName(symbol)) {
//		return undefined
//	}
//
//	// if this symbol is visible from its parent container, e.g. exported, then bail out
//	// if symbol correspond to the union property - bail out
//	if (symbol.Parent || (symbol.flags & SymbolFlags.Transient && (<TransientSymbol>symbol).checkFlags & CheckFlags.SyntheticProperty)) {
//		return undefined
//	}
//
//	let scope *types.Node
//
//	var declarations = symbol.getDeclarations()
//	if (declarations) {
//		for (var declaration of declarations) {
//			var container = getContainerNode(declaration)
//
//			if (!container) {
//				return undefined
//			}
//
//			if (scope && scope != container) {
//				// Different declarations have different containers, bail out
//				return undefined
//			}
//
//			if (container.Kind == syntaxkind.SourceFile && !isExternalModule(<SourceFile>container)) {
//				// This is a global variable and not an external module, any declaration defined
//				// within this scope is visible outside the file
//				return undefined
//			}
//
//			// The search scope is the container ast
//			scope = container
//		}
//	}
//
//	return scope
//}
//
//func getPossibleSymbolReferencePositions(ctx context.Context, sourceFile *types.SourceFile, symbolName string, start int, end int) []int {
//	var positions []int = []
//
//	/// TODO Cache symbol existence for files to save text search
//	// Also, need to make this work for unicode escapes.
//
//	// Be resilient in the face of a symbol with no name or zero length name
//	if (!symbolName || !symbolName.length) {
//		return positions
//	}
//
//	var text = sourceFile.text
//	var sourceLength = text.length
//	var symbolNameLength = symbolName.length
//
//	let position = text.indexOf(symbolName, start)
//	while (position >= 0) {
//		cancellationToken.throwIfCancellationRequested()
//
//		// If we are past the end, stop looking
//		if (position > end) break
//
//		// We found a match.  Make sure it's not part of a larger word (i.e. the char
//		// before and after it have to be a non-identifier char).
//		var endPosition = position + symbolNameLength
//
//		if ((position == 0 || !isIdentifierPart(text.charCodeAt(position - 1), ScriptTarget.Latest)) &&
//			(endPosition == sourceLength || !isIdentifierPart(text.charCodeAt(endPosition), ScriptTarget.Latest))) {
//			// Found a real match.  Keep searching.
//			positions.push(position)
//		}
//		position = text.indexOf(symbolName, position + symbolNameLength + 1)
//	}
//
//	return positions
//}
//
//func getLabelReferencesInNode(ctx context.Context, container *types.Node, targetLabel *types.Identifier) []ReferencedSymbol {
//	var references []ReferenceEntry = []
//	var sourceFile = container.getSourceFile()
//	var labelName = targetLabel.text
//	var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd(), cancellationToken)
//	forEach(possiblePositions, position => {
//		cancellationToken.throwIfCancellationRequested()
//
//		var ast = getTouchingWord(sourceFile, position)
//		if (!ast || ast.getWidth() != labelName.length) {
//			return
//		}
//
//		// Only pick labels that are either the target label, or have a target that is the target label
//		if (ast == targetLabel ||
//			(isJumpStatementTarget(ast) && getTargetLabel(ast, labelName) == targetLabel)) {
//			references.push(getReferenceEntryFromNode(ast))
//		}
//	})
//
//	var definition ReferencedSymbolDefinitionInfo = {
//		containerKind "",
//		containerName "",
//		fileName targetLabel.getSourceFile().fileName,
//		kind ScriptElementKind.label,
//		name labelName,
//		textSpan createTextSpanFromNode(targetLabel, sourceFile),
//		displayParts [displayPart(labelName, SymbolDisplayPartKind.text)]
//	}
//
//	return [{ definition, references }]
//}
//
//func isValidReferencePosition(ast *types.Node, searchSymbolName string) bool {
//	// Compare the length so we filter out strict superstrings of the symbol we are looking for
//	switch (ast && ast.Kind) {
//		case syntaxkind.Identifier
//			return ast.getWidth() == searchSymbolName.length
//
//		case syntaxkind.StringLiteral
//			return (isLiteralNameOfPropertyDeclarationOrIndexAccess(ast) || isNameOfExternalModuleImportOrDeclaration(ast)) &&
//				// For string literals we have two additional chars for the quotes
//				ast.getWidth() == searchSymbolName.length + 2
//
//		case syntaxkind.NumericLiteral
//			return isLiteralNameOfPropertyDeclarationOrIndexAccess(ast) && ast.getWidth() == searchSymbolName.length
//
//		default
//			return false
//	}
//}
//
//func getAllReferencesForKeyword(ctx context.Context, sourceFiles []*types.SourceFile, keywordKind syntaxkind.SyntaxKind) []ReferencedSymbol {
//	//var name = tokenToString(keywordKind)
//	//var references []ReferenceEntry = []
//	//for (var sourceFile of sourceFiles) {
//	//	cancellationToken.throwIfCancellationRequested()
//	//	addReferencesForKeywordInFile(sourceFile, keywordKind, name, cancellationToken, references)
//	//}
//	//
//	//if (!references.length) return undefined
//	//
//	//var definition ReferencedSymbolDefinitionInfo = {
//	//	containerKind "",
//	//	containerName "",
//	//	fileName references[0].fileName,
//	//	kind ScriptElementKind.keyword,
//	//	name,
//	//	textSpan references[0].textSpan,
//	//	displayParts [{ text name, kind ScriptElementKind.keyword }]
//	//}
//	//
//	//return [{ definition, references }]
//}
//
//func addReferencesForKeywordInFile(ctx context.Context, sourceFile *types.SourceFile, kind syntaxkind.SyntaxKind, searchText string, references []ReferenceEntry) {
//	var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, sourceFile.getStart(), sourceFile.getEnd(), cancellationToken)
//	for (var position of possiblePositions) {
//		cancellationToken.throwIfCancellationRequested()
//		var referenceLocation = getTouchingPropertyName(sourceFile, position)
//		if (referenceLocation.Kind == kind) {
//			references.push({
//				textSpan createTextSpanFromNode(referenceLocation),
//				fileName sourceFile.fileName,
//				isWriteAccess false,
//				isDefinition false,
//			})
//		}
//	}
//}
//
///** Search within ast "container" for references for a search value, where the search value is defined as a
//	 * tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
//	* searchLocation a ast where the search value
//	*/
//func getReferencesInNode(ctx context.Context,
//	container *types.Node,
//	searchSymbol *types.Symbol,
//	searchText string,
//	searchLocation *types.Node,
//	searchMeaning SemanticMeaning,
//	findInStrings bool,
//	findInComments bool,
//	result []ReferencedSymbol,
//	symbolToIndex []int,
//	implementations bool,
//	typeChecker types.ITypeChecker,
//	searchSymbols []*types.Symbol,
//	inheritsFromCache map[string]bool)  {
//	//
//	//var sourceFile = container.getSourceFile()
//	//
//	//var start = findInComments ? container.getFullStart()  container.getStart()
//	//var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, start, container.getEnd(), cancellationToken)
//	//
//	//var parents = getParentSymbolsOfPropertyAccess()
//	//
//	//for (var position of possiblePositions) {
//	//	cancellationToken.throwIfCancellationRequested()
//	//
//	//	var referenceLocation = getTouchingPropertyName(sourceFile, position)
//	//	if (!isValidReferencePosition(referenceLocation, searchText)) {
//	//		// This wasn't the start of a token.  Check to see if it might be a
//	//		// match in a comment or string if that's what the caller is asking
//	//		// for.
//	//		if (!implementations && ((findInStrings && isInString(sourceFile, position)) ||
//	//			(findInComments && isInNonReferenceComment(sourceFile, position)))) {
//	//
//	//			// In the case where we're looking inside comments/strings, we don't have
//	//			// an actual definition.  So just use 'undefined' here.  Features like
//	//			// 'Rename' won't care (as they ignore the definitions), and features like
//	//			// 'FindReferences' will just filter out these results.
//	//			result.push({
//	//				definition undefined,
//	//				references [{
//	//					fileName sourceFile.fileName,
//	//					textSpan createTextSpan(position, searchText.length),
//	//					isWriteAccess false,
//	//					isDefinition false
//	//				}]
//	//			})
//	//		}
//	//		continue
//	//	}
//	//
//	//	if (!(getMeaningFromLocation(referenceLocation) & searchMeaning)) {
//	//		continue
//	//	}
//	//
//	//	var referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation)
//	//	if (referenceSymbol) {
//	//		var referenceSymbolDeclaration = referenceSymbol.valueDeclaration
//	//		var shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration)
//	//		var relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation,
//	//			/*searchLocationIsConstructor*/ searchLocation.Kind == syntaxkind.ConstructorKeyword, parents, inheritsFromCache, typeChecker)
//	//
//	//		if (relatedSymbol) {
//	//			addReferenceToRelatedSymbol(referenceLocation, relatedSymbol)
//	//		}
//	//		/* Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment
//	//		 * has two meanings property name and property value. Therefore when we do findAllReference at the position where
//	//		 * an identifier is declared, the language service should return the position of the variable declaration as well as
//	//		 * the position in short-hand property assignment excluding property accessing. However, if we do findAllReference at the
//	//		 * position of property accessing, the referenceEntry of such position will be handled in the first case.
//	//		 */
//	//		else if (!(referenceSymbol.flags & SymbolFlags.Transient) && contains(searchSymbols, shorthandValueSymbol)) {
//	//			addReferenceToRelatedSymbol(referenceSymbolDeclaration.name, shorthandValueSymbol)
//	//		}
//	//		else if (searchLocation.Kind == syntaxkind.ConstructorKeyword) {
//	//			findAdditionalConstructorReferences(referenceSymbol, referenceLocation)
//	//		}
//	//	}
//	//}
//	//return
//	//
//	///* If we are just looking for implementations and this is a property access expression, we need to get the
//	// * symbol of the local type of the symbol the property is being accessed on. This is because our search
//	// * symbol may have a different parent symbol if the local type's symbol does not declare the property
//	// * being accessed (i.e. it is declared in some parent class or interface)
//	// */
//	//function getParentSymbolsOfPropertyAccess() []Symbol | undefined {
//	//	if (implementations) {
//	//		var propertyAccessExpression = getPropertyAccessExpressionFromRightHandSide(searchLocation)
//	//		if (propertyAccessExpression) {
//	//			var localParentType = typeChecker.getTypeAtLocation(propertyAccessExpression.expression)
//	//			if (localParentType) {
//	//				if (localParentType.symbol && localParentType.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) && localParentType.symbol != searchSymbol.Parent) {
//	//					return [localParentType.symbol]
//	//				}
//	//				else if (localParentType.flags & TypeFlags.UnionOrIntersection) {
//	//					return getSymbolsForClassAndInterfaceComponents(<UnionOrIntersectionType>localParentType)
//	//				}
//	//			}
//	//		}
//	//	}
//	//}
//	//
//	///** Adds references when a constructor is used with `new this()` in its own class and `super()` calls in subclasses.  */
//	//function findAdditionalConstructorReferences(referenceSymbol *types.Symbol, referenceLocation *types.Node) void {
//	//	Debug.assert(isClassLike(searchSymbol.valueDeclaration))
//	//
//	//	var referenceClass = referenceLocation.Parent
//	//	if (referenceSymbol == searchSymbol && isClassLike(referenceClass)) {
//	//		Debug.assert(referenceClass.name == referenceLocation)
//	//		// This is the class declaration containing the constructor.
//	//		addReferences(findOwnConstructorCalls(searchSymbol, sourceFile))
//	//	}
//	//	else {
//	//		// If this class appears in `extends C`, then the extending class' "super" calls are references.
//	//		var classExtending = tryGetClassByExtendingIdentifier(referenceLocation)
//	//		if (classExtending && isClassLike(classExtending) && followAliasIfNecessary(referenceSymbol, referenceLocation, typeChecker) == searchSymbol) {
//	//			addReferences(superConstructorAccesses(classExtending))
//	//		}
//	//	}
//	//}
//	//
//	//function addReferences(references []Node) void {
//	//	if (references.length) {
//	//		var referencedSymbol = getReferencedSymbol(searchSymbol)
//	//		addRange(referencedSymbol.references, map(references, getReferenceEntryFromNode))
//	//	}
//	//}
//	//
//	//function getReferencedSymbol(symbol *types.Symbol) ReferencedSymbol {
//	//	var symbolId = getSymbolId(symbol)
//	//	let index = symbolToIndex[symbolId]
//	//	if (index == undefined) {
//	//		index = result.length
//	//		symbolToIndex[symbolId] = index
//	//
//	//		result.push({
//	//			definition getDefinition(symbol, searchLocation, typeChecker),
//	//			references []
//	//		})
//	//	}
//	//
//	//	return result[index]
//	//}
//	//
//	//function addReferenceToRelatedSymbol(ast *types.Node, relatedSymbol *types.Symbol) {
//	//	var references = getReferencedSymbol(relatedSymbol).references
//	//	if (implementations) {
//	//		getImplementationReferenceEntryForNode(ast, references, typeChecker)
//	//	}
//	//	else {
//	//		references.push(getReferenceEntryFromNode(ast))
//	//	}
//	//}
//}
//
//func getPropertyAccessExpressionFromRightHandSide(ast *types.Node) *types.PropertyAccessExpression {
//	return isRightSideOfPropertyAccess(ast) && <PropertyAccessExpression>ast.Parent
//}
//
///** `classSymbol` is the class where the constructor was defined.
// * Reference the constructor and all calls to `new this()`.
// */
//func findOwnConstructorCalls(classSymbol *types.Symbol, sourceFile *types.SourceFile) []*types.Node {
//	var result []Node = []
//
//	for (var decl of classSymbol.members.get("__constructor").declarations) {
//		var ctrKeyword = ts.findChildOfKind(decl, ts.syntaxkind.ConstructorKeyword, sourceFile)!
//		Debug.assert(decl.Kind == syntaxkind.Constructor && !!ctrKeyword)
//		result.push(ctrKeyword)
//	}
//
//	classSymbol.exports.forEach(member => {
//		var decl = member.valueDeclaration
//		if (decl && decl.Kind == syntaxkind.MethodDeclaration) {
//			var body = (<MethodDeclaration>decl).body
//			if (body) {
//				forEachDescendantOfKind(body, syntaxkind.ThisKeyword, thisKeyword => {
//					if (isNewExpressionTarget(thisKeyword)) {
//						result.push(thisKeyword)
//					}
//				})
//			}
//		}
//	})
//
//	return result
//}
//
///** Find references to `super` in the constructor of an extending class.  */
//func superConstructorAccesses(cls *types.ClassDeclaration) []*types.Node {
//	var symbol = cls.symbol
//	var ctr = symbol.members.get("__constructor")
//	if (!ctr) {
//		return []
//	}
//
//	var result []Node = []
//	for (var decl of ctr.declarations) {
//		Debug.assert(decl.Kind == syntaxkind.Constructor)
//		var body = (<ConstructorDeclaration>decl).body
//		if (body) {
//			forEachDescendantOfKind(body, syntaxkind.SuperKeyword, ast => {
//				if (isCallExpressionTarget(ast)) {
//					result.push(ast)
//				}
//			})
//		}
//	}
//	return result
//}
//
//func getImplementationReferenceEntryForNode(refNode *types.Node, result []ReferenceEntry, typeChecker types.ITypeChecker) {
//	// Check if we found a function/propertyAssignment/method with an implementation or initializer
//	if (isDeclarationName(refNode) && isImplementation(refNode.Parent)) {
//		result.push(getReferenceEntryFromNode(refNode.Parent))
//	}
//	else if (refNode.Kind == syntaxkind.Identifier) {
//		if (refNode.Parent.Kind == syntaxkind.ShorthandPropertyAssignment) {
//			// Go ahead and dereference the shorthand assignment by going to its definition
//			getReferenceEntriesForShorthandPropertyAssignment(refNode, typeChecker, result)
//		}
//
//		// Check if the ast is within an extends or implements clause
//		var containingClass = getContainingClassIfInHeritageClause(refNode)
//		if (containingClass) {
//			result.push(getReferenceEntryFromNode(containingClass))
//			return
//		}
//
//		// If we got a type reference, try and see if the reference applies to any expressions that can implement an interface
//		var containingTypeReference = getContainingTypeReference(refNode)
//		if (containingTypeReference) {
//			var parent = containingTypeReference.Parent
//			if (isVariableLike(parent) && parent.type == containingTypeReference && parent.initializer && isImplementationExpression(parent.initializer)) {
//				maybeAdd(getReferenceEntryFromNode(parent.initializer))
//			}
//			else if (isFunctionLike(parent) && parent.type == containingTypeReference && parent.body) {
//				if (parent.body.Kind == syntaxkind.Block) {
//					forEachReturnStatement(<Block>parent.body, returnStatement => {
//						if (returnStatement.expression && isImplementationExpression(returnStatement.expression)) {
//							maybeAdd(getReferenceEntryFromNode(returnStatement.expression))
//						}
//					})
//				}
//				else if (isImplementationExpression(<Expression>parent.body)) {
//					maybeAdd(getReferenceEntryFromNode(parent.body))
//				}
//			}
//			else if (isAssertionExpression(parent) && isImplementationExpression(parent.expression)) {
//				maybeAdd(getReferenceEntryFromNode(parent.expression))
//			}
//		}
//	}
//
//	// Type nodes can contain multiple references to the same type. For example
//	//      let x Foo & (Foo & Bar) = ...
//	// Because we are returning the implementation locations and not the identifier locations,
//	// duplicate entries would be returned here as each of the type references is part of
//	// the same implementation. For that reason, check before we add a new entry
//	function maybeAdd(a ReferenceEntry) {
//		if (!forEach(result, b => a.fileName == b.fileName && a.textSpan.start == b.textSpan.start && a.textSpan.length == b.textSpan.length)) {
//			result.push(a)
//		}
//	}
//}
//
//func getSymbolsForClassAndInterfaceComponents(t UnionOrIntersectionType, result []*types.Symbol) []*types.Symbol {
//	for (var componentType of type.types) {
//		if (componentType.symbol && componentType.symbol.getFlags() & (SymbolFlags.Class | SymbolFlags.Interface)) {
//			result.push(componentType.symbol)
//		}
//		if (componentType.getFlags() & TypeFlags.UnionOrIntersection) {
//			getSymbolsForClassAndInterfaceComponents(<UnionOrIntersectionType>componentType, result)
//		}
//	}
//	return result
//}
//
//func getContainingTypeReference(ast *types.Node) *types.Node {
//	let topLevelTypeReference *types.Node = undefined
//
//	while (ast) {
//		if (isTypeNode(ast)) {
//			topLevelTypeReference = ast
//		}
//		ast = ast.Parent
//	}
//
//	return topLevelTypeReference
//}
//
//func getContainingClassIfInHeritageClause(ast *types.Node) *types.ClassDeclaration {
//	if (ast && ast.Parent) {
//		if (ast.Kind == syntaxkind.ExpressionWithTypeArguments
//			&& ast.Parent.Kind == syntaxkind.HeritageClause
//			&& isClassLike(ast.Parent.Parent)) {
//			return ast.Parent.Parent
//		}
//
//		else if (ast.Kind == syntaxkind.Identifier || ast.Kind == syntaxkind.PropertyAccessExpression) {
//			return getContainingClassIfInHeritageClause(ast.Parent)
//		}
//	}
//	return undefined
//}
//
///**
// * Returns true if this is an expression that can be considered an implementation
// */
//func isImplementationExpression(ast *types.Expression) bool {
//	switch (ast.Kind) {
//		case syntaxkind.ParenthesizedExpression
//			return isImplementationExpression((<ParenthesizedExpression>ast).expression)
//		case syntaxkind.ArrowFunction
//		case syntaxkind.ArrowFunction
//		case syntaxkind.ObjectLiteralExpression
//		case syntaxkind.ClassExpression
//		case syntaxkind.ArrayLiteralExpression
//			return true
//		default
//			return false
//	}
//}
//
///**
// * Determines if the parent symbol occurs somewhere in the child's ancestry. If the parent symbol
// * is an interface, determines if some ancestor of the child symbol extends or inherits from it.
// * Also takes in a cache of previous results which makes this slightly more efficient and is
// * necessary to avoid potential loops like so
// *     class A extends B { }
// *     class B extends A { }
// *
// * We traverse the AST rather than using the type checker because users are typically only interested
// * in explicit implementations of an interface/class when calling "Go to Implementation". Sibling
// * implementations of types that share a common ancestor with the type whose implementation we are
// * searching for need to be filtered out of the results. The type checker doesn't let us make the
// * distinction between structurally compatible implementations and explicit implementations, so we
// * must use the AST.
// *
// * @param child         A class or interface Symbol
// * @param parent        Another class or interface Symbol
// * @param cachedResults A map of symbol id pairs (i.e. "child,parent") to booleans indicating previous results
// */
//func explicitlyInheritsFrom(child *types.Symbol, parent *types.Symbol, cachedResults map[string]bool, typeChecker types.ITypeChecker) bool {
//	var parentIsInterface = parent.getFlags() & SymbolFlags.Interface
//	return searchHierarchy(child)
//
//	function searchHierarchy(symbol *types.Symbol) bool {
//		if (symbol == parent) {
//			return true
//		}
//
//		var key = getSymbolId(symbol) + "," + getSymbolId(parent)
//		var cached = cachedResults.get(key)
//		if (cached != undefined) {
//			return cached
//		}
//
//		// Set the key so that we don't infinitely recurse
//		cachedResults.set(key, false)
//
//		var inherits = forEach(symbol.getDeclarations(), declaration => {
//			if (isClassLike(declaration)) {
//				if (parentIsInterface) {
//					var interfaceReferences = getClassImplementsHeritageClauseElements(declaration)
//					if (interfaceReferences) {
//						for (var typeReference of interfaceReferences) {
//							if (searchTypeReference(typeReference)) {
//								return true
//							}
//						}
//					}
//				}
//				return searchTypeReference(getClassExtendsHeritageClauseElement(declaration))
//			}
//			else if (declaration.Kind == syntaxkind.InterfaceDeclaration) {
//				if (parentIsInterface) {
//					return forEach(getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration), searchTypeReference)
//				}
//			}
//			return false
//		})
//
//		cachedResults.set(key, inherits)
//		return inherits
//	}
//
//	function searchTypeReference(typeReference ExpressionWithTypeArguments) bool {
//		if (typeReference) {
//			var type = typeChecker.getTypeAtLocation(typeReference)
//			if (type && type.symbol) {
//				return searchHierarchy(type.symbol)
//			}
//		}
//		return false
//	}
//}
//
//func getReferencesForSuperKeyword(ctx context.Context, superKeyword *types.Node, typeChecker types.ITypeChecker) []ReferencedSymbol {
//	//let searchSpaceNode = getSuperContainer(superKeyword, /*stopOnFunctions*/ false)
//	//if (!searchSpaceNode) {
//	//	return undefined
//	//}
//	//// Whether 'super' occurs in a static context within a class.
//	//let staticFlag = ModifierFlags.Static
//	//
//	//switch (searchSpaceNode.Kind) {
//	//	case syntaxkind.PropertyDeclaration
//	//	case syntaxkind.PropertySignature
//	//	case syntaxkind.MethodDeclaration
//	//	case syntaxkind.MethodSignature
//	//	case syntaxkind.Constructor
//	//	case syntaxkind.GetAccessor
//	//	case syntaxkind.SetAccessor
//	//		staticFlag &= getModifierFlags(searchSpaceNode)
//	//		searchSpaceNode = searchSpaceNode.Parent; // re-assign to be the owning class
//	//		break
//	//	default
//	//		return undefined
//	//}
//	//
//	//var references []ReferenceEntry = []
//	//
//	//var sourceFile = searchSpaceNode.getSourceFile()
//	//var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd(), cancellationToken)
//	//for (var position of possiblePositions) {
//	//	cancellationToken.throwIfCancellationRequested()
//	//
//	//	var ast = getTouchingWord(sourceFile, position)
//	//
//	//	if (!ast || ast.Kind != syntaxkind.SuperKeyword) {
//	//		continue
//	//	}
//	//
//	//	var container = getSuperContainer(ast, /*stopOnFunctions*/ false)
//	//
//	//	// If we have a 'super' container, we must have an enclosing class.
//	//	// Now make sure the owning class is the same as the search-space
//	//	// and has the same static qualifier as the original 'super's owner.
//	//	if (container && (ModifierFlags.Static & getModifierFlags(container)) == staticFlag && container.Parent.symbol == searchSpaceNode.symbol) {
//	//		references.push(getReferenceEntryFromNode(ast))
//	//	}
//	//}
//	//
//	//var definition = getDefinition(searchSpaceNode.symbol, superKeyword, typeChecker)
//	//return [{ definition, references }]
//}
//
//func getReferencesForThisKeyword(ctx context.Context, thisOrSuperKeyword *types.Node, sourceFiles []*types.SourceFile, typeChecker types.ITypeChecker) []ReferencedSymbol {
//	//let searchSpaceNode = getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false)
//	//
//	//// Whether 'this' occurs in a static context within a class.
//	//let staticFlag = ModifierFlags.Static
//	//
//	//switch (searchSpaceNode.Kind) {
//	//	case syntaxkind.MethodDeclaration
//	//	case syntaxkind.MethodSignature
//	//		if (isObjectLiteralMethod(searchSpaceNode)) {
//	//			break
//	//		}
//	//	// fall through
//	//	case syntaxkind.PropertyDeclaration
//	//	case syntaxkind.PropertySignature
//	//	case syntaxkind.Constructor
//	//	case syntaxkind.GetAccessor
//	//	case syntaxkind.SetAccessor
//	//		staticFlag &= getModifierFlags(searchSpaceNode)
//	//		searchSpaceNode = searchSpaceNode.Parent; // re-assign to be the owning class
//	//		break
//	//	case syntaxkind.SourceFile
//	//		if (isExternalModule(<SourceFile>searchSpaceNode)) {
//	//			return undefined
//	//		}
//	//	// Fall through
//	//	case syntaxkind.FunctionDeclaration
//	//	case syntaxkind.ArrowFunction
//	//		break
//	//	// Computed properties in classes are not handled here because references to this are illegal,
//	//	// so there is no point finding references to them.
//	//	default
//	//		return undefined
//	//}
//	//
//	//var references []ReferenceEntry = []
//	//
//	//let possiblePositions []int
//	//if (searchSpaceNode.Kind == syntaxkind.SourceFile) {
//	//	forEach(sourceFiles, sourceFile => {
//	//		possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", sourceFile.getStart(), sourceFile.getEnd(), cancellationToken)
//	//		getThisReferencesInFile(sourceFile, sourceFile, possiblePositions, references)
//	//	})
//	//}
//	//else {
//	//	var sourceFile = searchSpaceNode.getSourceFile()
//	//	possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", searchSpaceNode.getStart(), searchSpaceNode.getEnd(), cancellationToken)
//	//	getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, references)
//	//}
//	//
//	//var thisOrSuperSymbol = typeChecker.getSymbolAtLocation(thisOrSuperKeyword)
//	//
//	//var displayParts = thisOrSuperSymbol && SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(
//	//	typeChecker, thisOrSuperSymbol, thisOrSuperKeyword.getSourceFile(), getContainerNode(thisOrSuperKeyword), thisOrSuperKeyword).displayParts
//	//
//	//return [{
//	//	definition {
//	//		containerKind "",
//	//		containerName "",
//	//		fileName thisOrSuperKeyword.getSourceFile().fileName,
//	//		kind ScriptElementKind.variableElement,
//	//		name "this",
//	//		textSpan createTextSpanFromNode(thisOrSuperKeyword),
//	//		displayParts
//	//	},
//	//	references references
//	//}]
//	//
//	//function getThisReferencesInFile(sourceFile SourceFile, searchSpaceNode *types.Node, possiblePositions []int, result []ReferenceEntry) void {
//	//	forEach(possiblePositions, position => {
//	//		cancellationToken.throwIfCancellationRequested()
//	//
//	//		var ast = getTouchingWord(sourceFile, position)
//	//		if (!ast || !isThis(ast)) {
//	//			return
//	//		}
//	//
//	//		var container = getThisContainer(ast, /* includeArrowFunctions */ false)
//	//
//	//		switch (searchSpaceNode.Kind) {
//	//			case syntaxkind.ArrowFunction
//	//			case syntaxkind.FunctionDeclaration
//	//				if (searchSpaceNode.symbol == container.symbol) {
//	//					result.push(getReferenceEntryFromNode(ast))
//	//				}
//	//				break
//	//			case syntaxkind.MethodDeclaration
//	//			case syntaxkind.MethodSignature
//	//				if (isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol == container.symbol) {
//	//					result.push(getReferenceEntryFromNode(ast))
//	//				}
//	//				break
//	//			case syntaxkind.ClassExpression
//	//			case syntaxkind.ClassDeclaration
//	//				// Make sure the container belongs to the same class
//	//				// and has the appropriate static modifier from the original container.
//	//				if (container.Parent && searchSpaceNode.symbol == container.Parent.symbol && (getModifierFlags(container) & ModifierFlags.Static) == staticFlag) {
//	//					result.push(getReferenceEntryFromNode(ast))
//	//				}
//	//				break
//	//			case syntaxkind.SourceFile
//	//				if (container.Kind == syntaxkind.SourceFile && !isExternalModule(<SourceFile>container)) {
//	//					result.push(getReferenceEntryFromNode(ast))
//	//				}
//	//				break
//	//		}
//	//	})
//	//}
//}
//
//func getReferencesForStringLiteral(ctx context.Context, ast *types.LiteralExpression, sourceFiles []*types.SourceFile, typeChecker types.ITypeChecker) []ReferencedSymbol {
//	//var type = getStringLiteralTypeForNode(ast, typeChecker)
//	//
//	//if (!type) {
//	//	// nothing to do here. moving on
//	//	return undefined
//	//}
//	//
//	//var references []ReferenceEntry = []
//	//
//	//for (var sourceFile of sourceFiles) {
//	//	var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, type.text, sourceFile.getStart(), sourceFile.getEnd(), cancellationToken)
//	//	getReferencesForStringLiteralInFile(sourceFile, type, possiblePositions, references)
//	//}
//	//
//	//return [{
//	//	definition {
//	//		containerKind "",
//	//		containerName "",
//	//		fileName ast.getSourceFile().fileName,
//	//		kind ScriptElementKind.variableElement,
//	//		name type.text,
//	//		textSpan createTextSpanFromNode(ast),
//	//		displayParts [displayPart(getTextOfNode(ast), SymbolDisplayPartKind.stringLiteral)]
//	//	},
//	//	references references
//	//}]
//	//
//	//function getReferencesForStringLiteralInFile(sourceFile SourceFile, searchType Type, possiblePositions []int, references []ReferenceEntry) void {
//	//	for (var position of possiblePositions) {
//	//		cancellationToken.throwIfCancellationRequested()
//	//
//	//		var ast = getTouchingWord(sourceFile, position)
//	//		if (!ast || ast.Kind != syntaxkind.StringLiteral) {
//	//			return
//	//		}
//	//
//	//		var type = getStringLiteralTypeForNode(<StringLiteral>ast, typeChecker)
//	//		if (type == searchType) {
//	//			references.push(getReferenceEntryFromNode(ast))
//	//		}
//	//	}
//	//}
//}
//
//func populateSearchSymbolSet(symbol *types.Symbol, location *types.Node, typeChecker types.ITypeChecker, implementations bool) []*types.Symbol {
//	// The search set contains at least the current symbol
//	var result = [symbol]
//
//	// If the location is name of property symbol from object literal destructuring pattern
//	// Search the property symbol
//	//      for ( { property p2 } of elems) { }
//	var containingObjectLiteralElement = getContainingObjectLiteralElement(location)
//	if (containingObjectLiteralElement && containingObjectLiteralElement.Kind != syntaxkind.ShorthandPropertyAssignment) {
//		var propertySymbol = getPropertySymbolOfDestructuringAssignment(location, typeChecker)
//		if (propertySymbol) {
//			result.push(propertySymbol)
//		}
//	}
//
//	// If the location is in a context sensitive location (i.e. in an object literal) try
//	// to get a contextual type for it, and add the property symbol from the contextual
//	// type to the search set
//	if (containingObjectLiteralElement) {
//		forEach(getPropertySymbolsFromContextualType(containingObjectLiteralElement, typeChecker), contextualSymbol => {
//			addRange(result, typeChecker.getRootSymbols(contextualSymbol))
//		})
//
//		/* Because in short-hand property assignment, location has two meaning  property name and as value of the property
//			* When we do findAllReference at the position of the short-hand property assignment, we would want to have references to position of
//			* property name and variable declaration of the identifier.
//			* Like in below example, when querying for all references for an identifier 'name', of the property assignment, the language service
//			* should show both 'name' in 'obj' and 'name' in variable declaration
//			*      var name = "Foo"
//			*      var obj = { name }
//			* In order to do that, we will populate the search set with the value symbol of the identifier as a value of the property assignment
//			* so that when matching with potential reference symbol, both symbols from property declaration and variable declaration
//			* will be included correctly.
//			*/
//		var shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(location.Parent)
//		if (shorthandValueSymbol) {
//			result.push(shorthandValueSymbol)
//		}
//	}
//
//	// If the symbol.valueDeclaration is a property parameter declaration,
//	// we should include both parameter declaration symbol and property declaration symbol
//	// Parameter Declaration symbol is only visible within function scope, so the symbol is stored in constructor.locals.
//	// Property Declaration symbol is a member of the class, so the symbol is stored in its class Declaration.symbol.members
//	if (symbol.valueDeclaration && symbol.valueDeclaration.Kind == syntaxkind.Parameter &&
//		isParameterPropertyDeclaration(<ParameterDeclaration>symbol.valueDeclaration)) {
//		addRange(result, typeChecker.getSymbolsOfParameterPropertyDeclaration(<ParameterDeclaration>symbol.valueDeclaration, symbol.name))
//	}
//
//	// If this is symbol of binding element without propertyName declaration in Expr binding pattern
//	// Include the property in the search
//	var bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, typeChecker)
//	if (bindingElementPropertySymbol) {
//		result.push(bindingElementPropertySymbol)
//	}
//
//	// If this is a union property, add all the symbols from all its session symbols in all unioned types.
//	// If the symbol is an instantiation from a another symbol (e.g. widened symbol) , add the root the list
//	for (var rootSymbol of typeChecker.getRootSymbols(symbol)) {
//		if (rootSymbol != symbol) {
//			result.push(rootSymbol)
//		}
//
//		// Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions
//		if (!implementations && rootSymbol.Parent && rootSymbol.Parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
//			getPropertySymbolsFromBaseTypes(rootSymbol.Parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ createMap<Symbol>(), typeChecker)
//		}
//	}
//
//	return result
//}
//
///**
// * Find symbol of the given property-name and add the symbol to the given result array
// * @param symbol a symbol to start searching for the given propertyName
// * @param propertyName a name of property to search for
// * @param result an array of symbol of found property symbols
// * @param previousIterationSymbolsCache a cache of symbol from previous iterations of calling this function to prevent infinite revisiting of the same symbol.
// *                                The value of previousIterationSymbol is undefined when the function is first called.
// */
//func getPropertySymbolsFromBaseTypes(symbol *types.Symbol, propertyName string, result []*types.Symbol,
//	previousIterationSymbolsCache map[string]*types.Symbol, typeChecker types.ITypeChecker)  {
//	if (!symbol) {
//		return
//	}
//
//	// If the current symbol is the same as the previous-iteration symbol, we can just return the symbol that has already been visited
//	// This is particularly important for the following cases, so that we do not infinitely visit the same symbol.
//	// For example
//	//      interface C extends C {
//	//          /*findRef*/propName string
//	//      }
//	// The first time getPropertySymbolsFromBaseTypes is called when finding-all-references at propName,
//	// the symbol argument will be the symbol of an interface "C" and previousIterationSymbol is undefined,
//	// the function will add any found symbol of the property-name, then its sub-routine will call
//	// getPropertySymbolsFromBaseTypes again to walk up any base types to prevent revisiting already
//	// visited symbol, interface "C", the sub-routine will pass the current symbol as previousIterationSymbol.
//	if (previousIterationSymbolsCache.has(symbol.name)) {
//		return
//	}
//
//	if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
//		forEach(symbol.getDeclarations(), declaration => {
//			if (isClassLike(declaration)) {
//				getPropertySymbolFromTypeReference(getClassExtendsHeritageClauseElement(<ClassDeclaration>declaration))
//				forEach(getClassImplementsHeritageClauseElements(<ClassDeclaration>declaration), getPropertySymbolFromTypeReference)
//			}
//			else if (declaration.Kind == syntaxkind.InterfaceDeclaration) {
//				forEach(getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration), getPropertySymbolFromTypeReference)
//			}
//		})
//	}
//	return
//
//	function getPropertySymbolFromTypeReference(typeReference ExpressionWithTypeArguments) {
//		if (typeReference) {
//			var type = typeChecker.getTypeAtLocation(typeReference)
//			if (type) {
//				var propertySymbol = typeChecker.getPropertyOfType(type, propertyName)
//				if (propertySymbol) {
//					result.push(...typeChecker.getRootSymbols(propertySymbol))
//				}
//
//				// Visit the typeReference as well to see if it directly or indirectly use that property
//				previousIterationSymbolsCache.set(symbol.name, symbol)
//				getPropertySymbolsFromBaseTypes(type.symbol, propertyName, result, previousIterationSymbolsCache, typeChecker)
//			}
//		}
//	}
//}
//
//func getRelatedSymbol(searchSymbols []*types.Symbol, referenceSymbol *types.Symbol, referenceLocation *types.Node, searchLocationIsConstructor bool, parents []*types.Symbol, cache map[string]bool, typeChecker types.ITypeChecker) *types.Symbol {
//	if (contains(searchSymbols, referenceSymbol)) {
//		// If we are searching for constructor uses, they must be 'new' expressions.
//		return (!searchLocationIsConstructor || isNewExpressionTarget(referenceLocation)) ? referenceSymbol  undefined
//	}
//
//	// If the reference symbol is an alias, check if what it is aliasing is one of the search
//	// symbols but by looking up for related symbol of this alias so it can handle multiple level of indirectness.
//	var aliasSymbol = getAliasSymbolForPropertyNameSymbol(referenceSymbol, referenceLocation, typeChecker)
//	if (aliasSymbol) {
//		return getRelatedSymbol(searchSymbols, aliasSymbol, referenceLocation, searchLocationIsConstructor, parents, cache, typeChecker)
//	}
//
//	// If the reference location is in an object literal, try to get the contextual type for the
//	// object literal, lookup the property symbol in the contextual type, and use this symbol to
//	// compare to our searchSymbol
//	var containingObjectLiteralElement = getContainingObjectLiteralElement(referenceLocation)
//	if (containingObjectLiteralElement) {
//		var contextualSymbol = forEach(getPropertySymbolsFromContextualType(containingObjectLiteralElement, typeChecker), contextualSymbol =>
//			find(typeChecker.getRootSymbols(contextualSymbol), symbol => contains(searchSymbols, symbol)))
//
//		if (contextualSymbol) {
//			return contextualSymbol
//		}
//
//		// If the reference location is the name of property from object literal destructuring pattern
//		// Get the property symbol from the object literal's type and look if thats the search symbol
//		// In below eg. get 'property' from type of elems iterating type
//		//      for ( { property p2 } of elems) { }
//		var propertySymbol = getPropertySymbolOfDestructuringAssignment(referenceLocation, typeChecker)
//		if (propertySymbol && contains(searchSymbols, propertySymbol)) {
//			return propertySymbol
//		}
//	}
//
//	// If the reference location is the binding element and doesn't have property name
//	// then include the binding element in the related symbols
//	//      let { a }  { a }
//	var bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(referenceSymbol, typeChecker)
//	if (bindingElementPropertySymbol && contains(searchSymbols, bindingElementPropertySymbol)) {
//		return bindingElementPropertySymbol
//	}
//
//	// Unwrap symbols to get to the root (e.g. transient symbols as a result of widening)
//	// Or a union property, use its underlying unioned symbols
//	return forEach(typeChecker.getRootSymbols(referenceSymbol), rootSymbol => {
//		// if it is in the list, then we are done
//		if (contains(searchSymbols, rootSymbol)) {
//			return rootSymbol
//		}
//
//		// Finally, try all properties with the same name in any type the containing type extended or implemented, and
//		// see if any is in the list. If we were passed a parent symbol, only include types that are subtypes of the
//		// parent symbol
//		if (rootSymbol.Parent && rootSymbol.Parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
//			// Parents will only be defined if implementations is true
//			if (parents) {
//				if (!forEach(parents, parent => explicitlyInheritsFrom(rootSymbol.Parent, parent, cache, typeChecker))) {
//					return undefined
//				}
//			}
//
//			var result []Symbol = []
//			getPropertySymbolsFromBaseTypes(rootSymbol.Parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ createMap<Symbol>(), typeChecker)
//			return find(result, symbol => contains(searchSymbols, symbol))
//		}
//
//		return undefined
//	})
//}
//
//func getNameFromObjectLiteralElement(ast ObjectLiteralElement) {
//	if (ast.name.Kind == syntaxkind.ComputedPropertyName) {
//		var nameExpression = (<ComputedPropertyName>ast.name).expression
//		// treat computed property names where expression is string/numeric literal as just string/numeric literal
//		if (isStringOrNumericLiteral(nameExpression)) {
//			return (<LiteralExpression>nameExpression).text
//		}
//		return undefined
//	}
//	return (<Identifier | LiteralExpression>ast.name).text
//}
//
///** Gets all symbols for one property. Does not get symbols for every property. */
//func getPropertySymbolsFromContextualType(ast ObjectLiteralElement, typeChecker types.ITypeChecker) []Symbol | undefined {
//	var objectLiteral = <ObjectLiteralExpression>ast.Parent
//	var contextualType = typeChecker.getContextualType(objectLiteral)
//	var name = getNameFromObjectLiteralElement(ast)
//	if (name && contextualType) {
//		var result []Symbol = []
//		var symbol = contextualType.getProperty(name)
//		if (symbol) {
//			result.push(symbol)
//		}
//
//		if (contextualType.flags & TypeFlags.Union) {
//			forEach((<UnionType>contextualType).types, t => {
//				var symbol = t.getProperty(name)
//				if (symbol) {
//					result.push(symbol)
//				}
//			})
//		}
//		return result
//	}
//	return undefined
//}
//
///**
// * Given an initial searchMeaning, extracted from a location, widen the search scope based on the declarations
// * of the corresponding symbol. e.g. if we are searching for "Foo" in value position, but "Foo" references a class
// * then we need to widen the search to include type positions as well.
// * On the contrary, if we are searching for "Bar" in type position and we trace bar to an interface, and an uninstantiated
// * module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module)
// * do not intersect in any of the three spaces.
// */
//func getIntersectingMeaningFromDeclarations(meaning SemanticMeaning, declarations []*types.Declaration) SemanticMeaning {
//	if (declarations) {
//		let lastIterationMeaning SemanticMeaning
//		do {
//			// The result is order-sensitive, for instance if initialMeaning == Namespace, and declarations = [class, instantiated module]
//			// we need to consider both as they initialMeaning intersects with the module in the namespace space, and the module
//			// intersects with the class in the value space.
//			// To achieve that we will keep iterating until the result stabilizes.
//
//			// Remember the last meaning
//			lastIterationMeaning = meaning
//
//			for (var declaration of declarations) {
//				var declarationMeaning = getMeaningFromDeclaration(declaration)
//
//				if (declarationMeaning & meaning) {
//					meaning |= declarationMeaning
//				}
//			}
//		}
//		while (meaning != lastIterationMeaning)
//	}
//	return meaning
//}
//
//func isImplementation(ast *types.Node) bool {
//	if (!ast) {
//		return false
//	}
//	else if (isVariableLike(ast)) {
//		if (ast.initializer) {
//			return true
//		}
//		else if (ast.Kind == syntaxkind.VariableDeclaration) {
//			var parentStatement = getParentStatementOfVariableDeclaration(<VariableDeclaration>ast)
//			return parentStatement && hasModifier(parentStatement, ModifierFlags.Ambient)
//		}
//	}
//	else if (isFunctionLike(ast)) {
//		return !!ast.body || hasModifier(ast, ModifierFlags.Ambient)
//	}
//	else {
//		switch (ast.Kind) {
//			case syntaxkind.ClassDeclaration
//			case syntaxkind.ClassExpression
//			case syntaxkind.EnumDeclaration
//			case syntaxkind.ModuleDeclaration
//				return true
//		}
//	}
//	return false
//}
//
//func getParentStatementOfVariableDeclaration(ast *types.VariableDeclaration) *types.VariableStatement {
//	if (ast.Parent && ast.Parent.Parent && ast.Parent.Parent.Kind == syntaxkind.VariableStatement) {
//		Debug.assert(ast.Parent.Kind == syntaxkind.VariableDeclarationList)
//		return <VariableStatement>ast.Parent.Parent
//	}
//}
//
//func getReferenceEntriesForShorthandPropertyAssignment(ast *types.Node, typeChecker types.ITypeChecker, result []ReferenceEntry) {
//	var refSymbol = typeChecker.getSymbolAtLocation(ast)
//	var shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(refSymbol.valueDeclaration)
//
//	if (shorthandSymbol) {
//		for (var declaration of shorthandSymbol.getDeclarations()) {
//			if (getMeaningFromDeclaration(declaration) & SemanticMeaning.Value) {
//				result.push(getReferenceEntryFromNode(declaration))
//			}
//		}
//	}
//}
//
//func getReferenceEntryFromNode(ast *types.Node) ReferenceEntry {
//	let start = ast.getStart()
//	let end = ast.getEnd()
//
//	if (ast.Kind == syntaxkind.StringLiteral) {
//		start += 1
//		end -= 1
//	}
//
//	return {
//		fileName ast.getSourceFile().fileName,
//		textSpan createTextSpanFromBounds(start, end),
//		isWriteAccess isWriteAccess(ast),
//		isDefinition isDeclarationName(ast) || isLiteralComputedPropertyDeclarationName(ast)
//	}
//}
//
///** A ast is considered a writeAccess iff it is a name of a declaration or a target of an assignment */
//func isWriteAccess(ast *types.Node) bool {
//	if (ast.Kind == syntaxkind.Identifier && isDeclarationName(ast)) {
//		return true
//	}
//
//	var parent = ast.Parent
//	if (parent) {
//		if (parent.Kind == syntaxkind.PostfixUnaryExpression || parent.Kind == syntaxkind.PrefixUnaryExpression) {
//			return true
//		}
//		else if (parent.Kind == syntaxkind.BinaryExpression && (<BinaryExpression>parent).left == ast) {
//			var operator = (<BinaryExpression>parent).operatorToken.Kind
//			return syntaxkind.FirstAssignment <= operator && operator <= syntaxkind.LastAssignment
//		}
//	}
//
//	return false
//}
//
//func forEachDescendantOfKind(ast *types.Node, kind syntaxkind.SyntaxKind, action func (ast *types.Node)) {
//	forEachChild(ast, child => {
//		if (child.Kind == kind) {
//			action(child)
//		}
//		forEachDescendantOfKind(child, kind, action)
//	})
//}
//
///**
// * Returns the containing object literal property declaration given a possible name ast, e.g. "a" in x = { "a" 1 }
// */
//func getContainingObjectLiteralElement(ast *types.Node) ObjectLiteralElement {
//	switch (ast.Kind) {
//		case syntaxkind.StringLiteral
//		case syntaxkind.NumericLiteral
//			if (ast.Parent.Kind == syntaxkind.ComputedPropertyName) {
//				return isObjectLiteralPropertyDeclaration(ast.Parent.Parent) ? ast.Parent.Parent  undefined
//			}
//		// intential fall through
//		case syntaxkind.Identifier
//			return isObjectLiteralPropertyDeclaration(ast.Parent) && ast.Parent.name == ast ? ast.Parent  undefined
//	}
//	return undefined
//}
//
//func isObjectLiteralPropertyDeclaration(ast *types.Node) bool  {
//	switch (ast.Kind) {
//		case syntaxkind.PropertyAssignment
//		case syntaxkind.ShorthandPropertyAssignment
//		case syntaxkind.MethodDeclaration
//		case syntaxkind.GetAccessor
//		case syntaxkind.SetAccessor
//			return true
//	}
//	return false
//}
//
///** Get `C` given `N` if `N` is in the position `class C extends N` or `class C extends foo.N` where `N` is an identifier. */
//func tryGetClassByExtendingIdentifier(ast *types.Node) *types.ClassDeclaration6 {
//	return tryGetClassExtendingExpressionWithTypeArguments(climbPastSelectorExpression(ast).Parent)
//}
//
//func isNameOfExternalModuleImportOrDeclaration(ast *types.Node) bool {
//	if (ast.Kind == syntaxkind.StringLiteral) {
//		return isNameOfModuleDeclaration(ast) || isExpressionOfExternalModuleImportEqualsDeclaration(ast)
//	}
//
//	return false
//}
//
//func isImportDefaultSymbol(symbol *types.Symbol) bool {
//	return symbol.declarations[0].Kind == syntaxkind.ImportClause
//}